﻿using Abp.Auditing;
using Abp.BackgroundJobs;
using Abp.Dependency;
using Abp.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
using Mt.Site.Core.AccessStatistics.BackgroundJob;
using Mt.Site.Core.MultiTenancy.Config;
using Mt.Site.Core.Url;
using System;
using System.Threading.Tasks;

namespace Mt.Site.Core.AccessStatistics
{
    public class VisitorDataProvider : IVisitorDataProvider, ITransientDependency
    {
        public IClientInfoProvider ClientInfoProvider { get; set; }
        public const string VisitorIdCookieKey = "HMAccount";
        private readonly ITenancyUrlConfig _tenancyUrlConfig;
        private readonly IBackgroundJobManager _backgroundJobManager;
        private readonly IHttpContextAccessor _httpContextAccessor;

        //常见机器人标识
        private static string[] _spiders = "Spider|spider|bingbot|Googlebot|AdsBot|Yahoo! Slurp|YoudaoBot".Split('|');

        public VisitorDataProvider(
            ITenancyUrlConfig tenancyUrlConfig,
            IBackgroundJobManager backgroundJobManager,
            IHttpContextAccessor httpContextAccessor)
        {
            ClientInfoProvider = NullClientInfoProvider.Instance;

            _tenancyUrlConfig = tenancyUrlConfig;
            _backgroundJobManager = backgroundJobManager;
            _httpContextAccessor = httpContextAccessor;
        }

        public async Task ProcessDataAsync(
            string refererUrl, string url, 
            string resolution, string colorDepth, int windowHeight, bool cookieEnabled, string cultureName,
            string title)
        {
            var httpContext = _httpContextAccessor.HttpContext;
            if(httpContext == null)
            {
                return;
            }

            var agent = httpContext.Request.Headers[HeaderNames.UserAgent].ToString();
            var ip = ClientInfoProvider.ClientIpAddress;
            if (ip.IsNullOrEmpty() || agent.IsNullOrEmpty() || IsRobot(agent))
            {
                return;
            }

            var pageUrl = CleanPageUrl(url);
            if(pageUrl == null)
            {
                return;
            }


            if (ip.IndexOf(',') > 0)
            {
                ip = (ip.Split(',')[0]).Split(':')[0];
            }

            var visitorData = new VisitorArgs();
            visitorData.ClientIp = ip;
            visitorData.UserAgent = agent;

            var now = DateTime.Now; //统计数据录入时，按服务器的时区记录
            visitorData.VisitTime = now;

            visitorData.Url = pageUrl;
            bool isExternal;
            visitorData.RefererUrl = CleanRefererUrl(refererUrl,out isExternal);
            visitorData.RefererUrlIsExternal = isExternal;
            visitorData.CookieEnabled = cookieEnabled;

            visitorData.Resolution = resolution;
            visitorData.ColorDepth = colorDepth;
            visitorData.WindowHeight = windowHeight;
            visitorData.CultureName = cultureName;
            visitorData.Title = title;

            string cookie = _httpContextAccessor.HttpContext.Request.Cookies[VisitorIdCookieKey];
            if (cookie == null)
            {
                visitorData.IsNewVisitor = true;
                var newAccount = Guid.NewGuid().ToString("N");
                visitorData.HMAccount = newAccount;

                _httpContextAccessor.HttpContext.Response.Cookies.Append(
                    VisitorIdCookieKey,
                    newAccount,
                    new CookieOptions
                    {
                        Expires = now.AddYears(20),
                        Path = "/",
                        HttpOnly = true
                    }
                );
            }
            else
            {
                visitorData.IsNewVisitor = false;
                visitorData.HMAccount = cookie;
            }

            await _backgroundJobManager.EnqueueAsync<AccessStatisticsJob, VisitorArgs>(visitorData);
        }
        private string CleanPageUrl(string pageUrl)
        {
            try
            {
                var uri = new Uri(pageUrl);
                var domainName = UrlChecker.GetAuthority(uri).ToLower();
                if (!_tenancyUrlConfig.DomainNameList.Contains(domainName))
                {
                    return null;
                }

                return UrlChecker.GetUrlRemoveQueryAndFragment(pageUrl).RemovePostFix("/");
            }
            catch
            {
                return null;
            }
        }

        private string CleanRefererUrl(string refererUrl,out bool isExternal)
        {
            isExternal = false;

            if (refererUrl.IsNullOrEmpty())
            {
                return null;
            }

            try
            {
                var uri = new Uri(refererUrl);
                var domainName = UrlChecker.GetAuthority(uri).ToLower();
                if (!_tenancyUrlConfig.DomainNameList.Contains(domainName))
                {
                    isExternal = true;
                }

                return refererUrl;
            }
            catch
            {
                return null;
            }
        }

        //简略地判断一下，过滤大部分蜘蛛，后续解析时会再次过滤
        private static bool IsRobot(string agent)
        {
            foreach (var item in _spiders)
            {
                if (agent.IndexOf(item) > -1)
                {
                    return true;
                }
            }
            return false;
        }
    }
}
